package experiment.networkmodel;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;

public class SocketSpeaker implements Runnable, Updatable {

	protected Socket socket;
	protected Updatable caller;
	protected ObjectOutputStream objOut;
	protected ObjectInputStream objIn;
	protected volatile boolean listen;

	public SocketSpeaker(Socket listenTo, Updatable caller) {
		listen = true;
		this.caller = caller;
		socket = listenTo;

		try {
			objOut = new ObjectOutputStream(socket.getOutputStream());
		} catch (IOException e) {
			e.printStackTrace();
			System.err.println("Object output stream failed to be established");
		}

		try {
			objIn = new ObjectInputStream(socket.getInputStream());
		} catch (IOException e) {
			e.printStackTrace();
			System.err.println("Object input stream failed to be established");
		}

		System.out.println("New Socket speaker created");
	}

	@Override
	public void run() {
		System.out.println("Socket speaker thread started");
		try {
			objOut.write(1);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		listen();
		System.out.println("Socket speaker thread closed");
	}

	private void listen() {
		System.out.println("Now listening on the socket");
		Object temp = null;
		while (listen) {
			try {
				temp = objIn.readObject();
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
			caller.update(temp);
		}
		System.out.println("Listening stopped");
	}

	@Override
	public void update(Object obj) {
		System.out.println("Sending update to socket");
		try {
			objOut.writeObject(obj);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	@Override
	public void kill(int status) {
		System.out.println("Thread ended");
		listen = false;
		try {
			objOut.close();
			objIn.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		try {
			socket.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		System.err.println("Thread ended with status: " + status);
	}
}
